package utils

import (
	"encoding/hex"
	"errors"
	"log/slog"
	"math/rand"
	"regexp"
	"strings"

	"golang.org/x/text/cases"
	"golang.org/x/text/language"
)

var matchAllCap = regexp.MustCompile("([a-z0-9])([A-Z])")

func ToSnakeCase(str string) string {
	snake := matchAllCap.ReplaceAllString(str, "${1}_${2}")
	return strings.ToLower(snake)
}

func ToCamelCase(str string) string {
	if len(str) == 0 {
		return str
	}
	temp := strings.Split(str, "_")
	temp[0] = strings.ToLower(temp[0][:1]) + temp[0][1:]
	for i, r := range temp {
		if i > 0 {
			temp[i] = cases.Title(language.English).String(r)
		}
	}

	return strings.Join(temp, "")
}
func ToPascalCase(str string) string {
	if len(str) == 0 {
		return str
	}
	temp := strings.Split(str, "_")
	for i, r := range temp {
		temp[i] = cases.Title(language.English).String(r)
	}

	return strings.Join(temp, "")
}

func GenRandCode16() int64 {
	const maxValue int64 = 10000 * 10000 * 10000 * 10000
	const minValue int64 = 10000 * 10000 * 10000 * 1000
	var code = rand.Int63n(maxValue)
	if code < minValue {
		code = minValue*(rand.Int63n(9)+1) + code
	}
	return code
}

func GenRandCode12() int64 {
	const maxValue int64 = 10000 * 10000 * 10000
	const minValue int64 = 10000 * 10000 * 1000
	var code = rand.Int63n(maxValue)
	if code < minValue {
		code = minValue*(rand.Int63n(9)+1) + code
	}
	return code
}

func GenRandomString(length int) string {
	str := "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
	bytes := []byte(str)
	var result []byte
	for i := 0; i < length; i++ {
		result = append(result, bytes[rand.Intn(len(bytes))])
	}
	return string(result)
}

func GenRandomHex(length int) (string, error) {
	if length <= 0 {
		slog.Error("invalid length")
		return "", errors.New("invalid length")
	}

	codes := "0123456789abcdef"
	result := ""
	for i := 0; i < length; i++ {
		var index = rand.Intn(16)
		result += codes[index : index+1]
	}
	return result, nil
}

func GenRandomBytes(length int) ([]byte, error) {
	if length <= 0 {
		slog.Error("invalid length")
		return nil, errors.New("invalid length")
	}
	str, err := GenRandomHex(length * 2)
	if err != nil {
		slog.Error(err.Error())
		return nil, err
	}
	bytes, err := hex.DecodeString(str)
	if err != nil {
		slog.Error(err.Error())
		return nil, err
	}
	return bytes, nil
}

func IsEmptyValueStr(str string) bool {
	return len(str) == 0 || str == "null"
}
